<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>主题切换</title>
    <style>
      /* 提1：使用两个短横连接线 "--" 作为开头命名的名称即被称为自定义属性 */
      /* 在需要应用该属性的地方，使用 "var()函数" 并传入自定义属性的名称 */

      /* 提2：":root" 是一个伪类选择器，它用来匹配文档的 ->根元素<html> */
      :root {
        /* 亮色模式下的背景色 */
        --bg-color: #fff; /* ①声明自定义属性 */
        background-color: var(--bg-color); /* ②使用自定义属性 */
      }

      :root.dark {
        /* 暗色模式下的背景色 */
        --bg-color: #000;
      }

      /* 3.5 还需要禁用默认的淡入淡出动画，否则将影响我们自定义的动画效果 */
      ::view-transition-new(root),
      ::view-transition-old(root) {
        /* 3.6 关闭默认动画，否则影响自定义动画的执行 */
        animation: none;
      }

      /* 3.end同步： */
      .dark::view-transition-old(root) {
        z-index: 100;
      }
    </style>
  </head>
  <body>
    <button id="btn">切换主题</button>

    <script>
      const btn = document.getElementById('btn')

      btn.addEventListener('click', (e) => {
        // 1. 点击按钮时切换主题 (初步)
        // 细节1：这里, 通过的是 ->切换类名 ->中的 toggle()方法实现 ->来回切换效果...
        // document.documentElement.classList.toggle('dark')

        // 中步：过渡动画
        // 2. 使用 [View Transitions API] 实现 <过渡> 效果 (不用引入"其他JS包"即可实现)
        const transition = document.startViewTransition(() => {
          // 2.x 在 startViewTransition 中修改 DOM 状态产生动画
          document.documentElement.classList.toggle('dark')
        })
        // console.log(transition)

        // 3. 在 transition.ready 的 Promise 完成后，执行自定义动画
        // 等待伪元素创建完成(ready), 才开始执行后续代码...
        // ( 如下代码可直接上 MDN 查找 ->"View Transitions API" )
        transition.ready.then(() => {
          // 3.2 由于我们要从鼠标点击的位置开始做动画，所以我们需要先获取到鼠标的位置：
          const { clientX, clientY } = e

          // 3.3 计算半径，以鼠标点击的位置为圆心，到四个角的距离中最大的那个作为半径：
          // Math.hypot函数 ->返回所有参数的平方和的平方根
          const radius = Math.hypot(
            Math.max(clientX, innerWidth - clientX),
            Math.max(clientY, innerHeight - clientY)
          )

          // 3.end同步：
          const clipPath = [
            `circle(0% at ${clientX}px ${clientY}px)`,
            `circle(${radius}px at ${clientX}px ${clientY}px)`
          ]

          // 3.end 最终实现：
          const isDark = document.documentElement.classList.contains('dark')
        
          // 3.4 自定义动画 (该步代码 MDN 上也有实例...)
          document.documentElement.animate(
            // {
            // clipPath: [
            //   `circle(0% at ${clientX}px ${clientY}px)`,
            //   `circle(${radius}px at ${clientX}px ${clientY}px)`
            // ]
            // },

            {
              // 3.end同步 如果要切换到暗色主题，我们在过渡的时候从半径 100% 的圆开始，到 0% 的圆结束
              clipPath: isDark ? clipPath.reverse() : clipPath
            },
            {
              duration: 500, // 持续时间
              // easing: "ease-in", 默认
              // 指定要附加动画的伪元素 (MDN 也是写的 new)
              // pseudoElement: '::view-transition-new(root)'

              // 3.end同步 如果要切换到暗色主题，我们应该裁剪 view-transition-old(root) 的内容
              pseudoElement: isDark
                ? '::view-transition-old(root)'
                : '::view-transition-new(root)'
            }
          )
        })
      })
    </script>
  </body>
</html>
